home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr01 / halcn305.zip / GSXT_BRO.PAS < prev    next >
Pascal/Delphi Source File  |  1993-08-08  |  20KB  |  607 lines

  1. unit GSXT_Bro;
  2. {-----------------------------------------------------------------------------
  3.                                Browse Unit
  4.  
  5.        GSXT_Bro Copyright (c)  Richard F. Griffin
  6.  
  7.        28 June 1993
  8.  
  9.        102 Molded Stone Pl
  10.        Warner Robins, GA  31088
  11.  
  12.        -------------------------------------------------------------
  13.        This unit handles calls for a file browser.  Records may be
  14.        scrolled left, right, up and down in a window by using these
  15.        calls.  The dBase file must be initialized through
  16.        GSOBSHEL.PAS calls prior to calling these routines.
  17.        See XTRASTUF.PAS and BROWTEST.PAS for examples of use.
  18.  
  19.        Description:
  20.  
  21.           Procedure StartBrowse(lincnt, linwidth: integer);
  22.  
  23.              Initializes browse activity.  The lincnt argument is the
  24.              number of lines that can be displayed on screen.  The
  25.              linwidth argument is the line size to be displayed on
  26.              screen.  Must be called before any other command.
  27.  
  28.           Procedure ResetBrowse;
  29.  
  30.              Resets the browse function by releasing memory.  Must be
  31.              called to close the browse activity.
  32.  
  33.           Function GetBrowseHeader(bline: word): string;
  34.  
  35.              Returns the portion of the header line starting at bline
  36.              for the maximum length that can be displayed on screen.
  37.  
  38.           Function GetBrowseLine(linnum, bline: word): string;
  39.  
  40.              Returns the portion of the data record to be displayed
  41.              starting at bline position within the string array of the
  42.              record.  The function will return a string of the length
  43.              that can be displayed on screen.  Linnum is the row to be
  44.              selected, based on the record's relative position in the
  45.              display window.  UpdateBrowse must be called initially to
  46.              select the range of records to be displayed.
  47.  
  48.           Function GetBrowseRecord(linnum: integer): longint;
  49.  
  50.              Returns the physical record number for the record at linnum.
  51.              Linnum is the row to be selected, based on the record's
  52.              relative position in the display window.  UpdateBrowse must
  53.              be called initially to select the range of records to be
  54.              displayed.
  55.  
  56.           Function GetBrowseBar(bline: word): string;
  57.  
  58.              Returns a separator line to be placed between the header and
  59.              data records.  This line is created by scanning the portion
  60.              of the header line starting at bline for the maximum length
  61.              that can be displayed on screen.  If the position in the
  62.              header contains the value in broSeparator, then the value
  63.              from broIntersect is inserted in the line, otherwise the
  64.              value in broHorizontal is inserted.
  65.  
  66.           Procedure MoveBrowseLeft(var posn: word);
  67.  
  68.              Used to compute the scroll position for a scroll left.
  69.              Decrements posn by 1.  It then tests to see if posn is less
  70.              than 1 and sets it to 1 if it is less.  This value is used
  71.              by other calls to identify the starting scroll position for
  72.              GetBrowseLine and GetBrowseHeader.
  73.  
  74.           Procedure MoveBrowseRight(var posn: word);
  75.  
  76.              Used to compute the scroll position for a scroll right.
  77.              Increments posn by 1.  It then tests to see if posn is
  78.              greater than (length of the record - max line that can
  79.              be displayed), and adjusts to that length if greater.
  80.              This prevents scrolling beyond the length of the record.
  81.              The value returned in posn is used by other calls to
  82.              identify the starting scroll position for GetBrowseLine
  83.              and GetBrowseHeader.
  84.  
  85.           Procedure RenewBrowseLine(linnum: word);
  86.  
  87.              Rereads the physical record for the record displayed at
  88.              linnum.  Linnum is the row to be selected, based on the
  89.              record's relative position in the display window.
  90.              UpdateBrowse must be called initially to select the range
  91.              of records to be displayed.  This routine needs to be called
  92.              if a record is updated during the browse activity.
  93.  
  94. Procedure TabBrowseLeft(var posn: word);
  95.  
  96.              Used to compute the scroll position for a tab left.
  97.              Decrements posn to the start of the previous field, unless
  98.              already at field 1.  This value is used by other calls to
  99.              identify the starting scroll position for GetBrowseLine and
  100.              GetBrowseHeader.
  101.  
  102.           Procedure TabBrowseRight(var posn: word);
  103.  
  104.              Used to compute the scroll position for a tab right.
  105.              Increments posn to the start of the next field.  It then
  106.              tests to see if posn is greater than (length of the record -
  107.              max line that can be displayed), and adjusts to that length
  108.              if greater. This prevents scrolling beyond the length of
  109.              the record.  The value returned in posn is used by other
  110.              calls to identify the starting scroll position for
  111.              GetBrowseLine and GetBrowseHeader.
  112.  
  113.           Procedure UpdateBrowse(action: longint);
  114.  
  115.              Retrieves records from the database file based on the command
  116.              in action.  Valid commands are: broLnDn, broLnUp, broTop,
  117.              broBttm, broPgDn, and broPgUp.  It retrieves as many records
  118.              as is necessary to fill the number of lines specified in the
  119.              StartBrowse command.
  120.  
  121.    Changes
  122.  
  123.       07 Aug 93 - Fixed PageUp browses to run faster by using the Skip
  124.                   command.  Reading backwards a record at a time causes
  125.                   some systems to be extremely slow because of the cache
  126.                   techniques in these systems use.  The fix is to use one
  127.                   backwards read (the skip), and then forward reads.
  128.  
  129. ------------------------------------------------------------------------------}
  130.  
  131. interface
  132.  
  133. Uses
  134.    GSOB_Dte,
  135.    GSOB_Var,
  136.    GSOBShel,
  137. {$IFDEF WINDOWS}
  138.    Objects;
  139. {$ELSE}
  140.    GSOB_Obj;
  141. {$ENDIF}
  142.  
  143. const
  144.  
  145.    broSeparator  = #179;
  146.    broHorizontal = #196;
  147.    broIntersect  = #197;
  148.  
  149.    broLnDn = -1;
  150.    broLnUp = -2;
  151.    broTop  = -3;
  152.    broBttm = -4;
  153.    broPgDn = -5;
  154.    broPgUp = -6;
  155.  
  156. Procedure StartBrowse(lincnt, linwidth: integer);
  157. Procedure ResetBrowse;
  158. Procedure MoveBrowseLeft(var posn: word);
  159. Procedure MoveBrowseRight(var posn: word);
  160. Procedure TabBrowseLeft(var posn: word);
  161. Procedure TabBrowseRight(var posn: word);
  162. Procedure UpdateBrowse(action: longint);
  163. Function GetBrowseHeader(bline: word): string;
  164. Function GetBrowseLine(linnum, bline: word): string;
  165. Function GetBrowseRecord(linnum: integer): longint;
  166. Function GetBrowseBar(bline: word): string;
  167. Procedure RenewBrowseLine(linnum: word);
  168.  
  169. implementation
  170.  
  171. type
  172.    GSPbroLine = ^GSRbroLine;
  173.    GSRbroLine = record
  174.       LineRcrd :  longint;
  175.       LineText :  Array [0..16383] of byte;
  176.    end;
  177.  
  178.    GSPbroLineColl = ^GSObroLineColl;
  179.    GSObroLineColl = object(TCollection)
  180.       LineBufSize: integer;
  181.       LinesAvail : integer;
  182.       LinesWidth : integer;
  183.       LineHead   : GSPbroLine;
  184.       procedure  FreeItem(Item : pointer); virtual;
  185.       procedure  InsertItem(Item : pointer);
  186.       procedure  InsertItemAt(Item : pointer; i : integer);
  187.    end;
  188.  
  189. var
  190.    broObject : GSObroLineColl;
  191.    Separator : char;
  192.  
  193. {------------------------------------------------------------------------------
  194.                               GSObro_LineColl
  195. ------------------------------------------------------------------------------}
  196.  
  197. procedure GSObroLineColl.FreeItem(Item: Pointer);
  198. var
  199.    p : GSPbroLine absolute Item;
  200. begin
  201.    if Item <> nil then FreeMem(p, LineBufSize);
  202. end;
  203.  
  204. Procedure GSObroLineColl.InsertItem(Item: Pointer);
  205. var
  206.    p : GSPbroLine absolute Item;
  207. begin
  208.    Insert(p);
  209. end;
  210.  
  211. Procedure GSObroLineColl.InsertItemAt(Item: Pointer; i: integer);
  212. var
  213.    p : GSPbroLine absolute Item;
  214. begin
  215.    AtInsert(i,p);
  216. end;
  217.  
  218. {------------------------------------------------------------------------------
  219.                               Browse Routines
  220. ------------------------------------------------------------------------------}
  221.  
  222. Function SizeOfLine: word;
  223. var
  224.    ix : integer;
  225.    ls : word;
  226. begin
  227.    ls := 0;
  228.    with DBFActive^ do
  229.    begin
  230.       for ix := 1 to NumFields do
  231.       begin
  232.          ls := ls + FieldLen(ix) + 1;
  233.          if (FieldType(ix) = 'D') and GS_Date_Century then inc(ls,2);
  234.       end;
  235.       SizeOfLine := ls;
  236.    end;
  237. end;
  238.  
  239. Procedure MakeHeader;
  240. var
  241.    ix : integer;
  242.    iv : integer;
  243.    ls : word;
  244.    p  : PByteArray;
  245.    t  : string;
  246. begin
  247.    GetMem(p, broObject.LineBufSize);
  248.    broObject.LineHead := GSPbroLine(p);
  249.    FillChar(p^,broObject.LineBufSize,' ');
  250.    ls := 4;
  251.    with DBFActive^ do
  252.    begin
  253.       for ix := 1 to NumFields do
  254.       begin
  255.          iv := FieldLen(ix);
  256.          if (FieldType(ix) = 'D') and GS_Date_Century then inc(iv,2);
  257.          t := FieldName(ix);
  258.          if length(t) > iv then
  259.             move(t[1],p^[ls],iv)
  260.          else
  261.             move(t[1],p^[ls],length(t));
  262.          ls := ls + iv;
  263.          move(separator,p^[ls],1);
  264.          ls := ls + 1;
  265.       end;
  266.    end;
  267. end;
  268.  
  269. Function FillInLine: GSPbroLine;
  270. var
  271.    ix : integer;
  272.    ls : word;
  273.    p  : PByteArray;
  274.    t  : string;
  275. begin
  276.    GetMem(p, broObject.LineBufSize);
  277.    FillChar(p^,broObject.LineBufSize,' ');
  278.    ls := 4;
  279.    with DBFActive^ do
  280.    begin
  281.       for ix := 1 to NumFields do
  282.       begin
  283.          t := FieldGetN(ix);
  284.          case FieldType(ix) of
  285.             'C',
  286.             'G',
  287.             'L',
  288.             'N'  : begin
  289.                    end;
  290.             'D',
  291.             'M'  : begin
  292.                       t := StringGetN(ix);
  293.                   end;
  294.          end;
  295.          move(t[1],p^[ls],length(t));
  296.          ls := ls + FieldLen(ix);
  297.          if (FieldType(ix) = 'D') and GS_Date_Century then inc(ls,2);
  298.          move(separator,p^[ls],1);
  299.          ls := ls + 1;
  300.       end;
  301.       move(RecNumber,p^,4);
  302.       FillInLine := GSPbroLine(p);
  303.    end;
  304. end;
  305.  
  306. Procedure StartBrowse(lincnt, linwidth: integer);
  307. begin
  308.    Separator := broSeparator;
  309.    broObject.Init(lincnt, 8);
  310.    broObject.LineBufSize := SizeOfLine + 4;
  311.    broObject.LinesAvail := lincnt;
  312.    if linwidth > broObject.LineBufSize-4 then
  313.       linwidth := broObject.LineBufSize-4;
  314.    broObject.LinesWidth := linwidth;
  315.    MakeHeader;
  316. end;
  317.  
  318. Procedure ResetBrowse;
  319. begin
  320.    FreeMem(broObject.LineHead, broObject.LineBufSize);
  321.    broObject.Done;
  322. end;
  323.  
  324. Procedure MoveBrowseLeft(var posn: word);
  325. begin
  326.    dec(posn);
  327.    if posn <= 0 then posn := 1;
  328. end;
  329.  
  330. Procedure MoveBrowseRight(var posn: word);
  331. begin
  332.    inc(posn);
  333.    if posn > (broObject.LineBufSize - broObject.LinesWidth) - 3 then
  334.       posn := (broObject.LineBufSize - broObject.LinesWidth) - 3;
  335. end;
  336.  
  337. Procedure TabBrowseLeft(var posn: word);
  338. var
  339.    ix : integer;
  340.    lv : integer;
  341.    ls : word;
  342. begin
  343.    ls := 0;
  344.    lv := 0;
  345.    ix := 1;
  346.    with DBFActive^ do
  347.    begin
  348.       while (ix <= NumFields) and (posn > ls) do
  349.       begin
  350.          lv := ls;
  351.          ls := ls + FieldLen(ix) + 1;
  352.          if (FieldType(ix) = 'D') and GS_Date_Century then inc(ls,2);
  353.          inc(ix);
  354.       end;
  355.    end;
  356.    posn := lv;
  357.    if posn = 0 then posn := 1;
  358. end;
  359.  
  360. Procedure TabBrowseRight(var posn: word);
  361. var
  362.    ix : integer;
  363.    ls : word;
  364. begin
  365.    ls := 0;
  366.    ix := 1;
  367.    with DBFActive^ do
  368.    begin
  369.       while (ix <= NumFields) and (posn >= ls) do
  370.       begin
  371.          ls := ls + FieldLen(ix) + 1;
  372.          if (FieldType(ix) = 'D') and GS_Date_Century then inc(ls,2);
  373.          inc(ix);
  374.       end;
  375.    end;
  376.    posn := ls;
  377.    if posn > (broObject.LineBufSize - broObject.LinesWidth) - 3 then
  378.       posn := (broObject.LineBufSize - broObject.LinesWidth) - 3;
  379. end;
  380.  
  381.  
  382. Procedure UpdateBrowse(action: longint);
  383. var
  384.    ix : integer;
  385.    p  : GSPbroLine;
  386.    ln : longint;
  387. begin
  388.    with DBFActive^ do
  389.    begin
  390.       case action of
  391.          broLnDn      : begin
  392.                            p := broObject.At(broObject.Count-1);
  393.                            ln := p^.LineRcrd;
  394.                            Go(ln);
  395.                            GetRec(Next_Record);
  396.                            if not File_EOF then
  397.                            begin
  398.                               if broObject.Count >= broObject.LinesAvail then
  399.                                  broObject.Free(broObject.At(0));
  400.                               broObject.Insert(FillInLine);
  401.                            end;
  402.                         end;
  403.  
  404.          broLnUp      : begin
  405.                            p := broObject.At(0);
  406.                            ln := p^.LineRcrd;
  407.                            Go(ln);
  408.                            GetRec(Prev_Record);
  409.                            if not File_TOF then
  410.                            begin
  411.                               if broObject.Count >= broObject.LinesAvail then
  412.                                  broObject.Free
  413.                                            (broObject.At(broObject.Count-1));
  414.                               broObject.AtInsert(0, FillInLine);
  415.                            end;
  416.                         end;
  417.  
  418.          broTop       : begin
  419.                            broObject.FreeAll;
  420.                            GetRec(Top_Record);
  421.                            ix := 0;
  422.                            while (ix < broObject. LinesAvail) and
  423.                                  not File_EOF do
  424.                            begin
  425.                               broObject.Insert(FillInLine);
  426.                               GetRec(Next_Record);
  427.                               inc(ix);
  428.                            end;
  429.                         end;
  430.  
  431.          broBttm      : begin
  432.                            broObject.FreeAll;
  433.                            GetRec(Bttm_Record);
  434.                            ix := 0;
  435.                            while (ix < broObject.LinesAvail) and
  436.                                  not File_TOF do
  437.                            begin
  438.                               broObject.AtInsert(0,FillInLine);
  439.                               GetRec(Prev_Record);
  440.                               inc(ix);
  441.                            end;
  442.                         end;
  443.  
  444.          broPgDn      : begin
  445.                            p := broObject.At(broObject.Count-1);
  446.                            broObject.Delete(p);
  447.                            ln := p^.LineRcrd;
  448.                            broObject.FreeAll;
  449.                            broObject.Insert(p);
  450.                            Go(ln);
  451.                            GetRec(Next_Record);
  452.                            ix := 1;
  453.                            while (ix < broObject.LinesAvail) and
  454.                                  not File_EOF do
  455.                            begin
  456.                               broObject.Insert(FillInLine);
  457.                               if (ix < broObject.LinesAvail-1) then
  458.                                  GetRec(Next_Record);
  459.                               inc(ix);
  460.                            end;
  461.                         end;
  462.  
  463.          broPgUp      : begin
  464.  
  465.                            p := broObject.At(0);
  466.                            ln := p^.LineRcrd;
  467.                            Go(ln);
  468.                            Skip((broObject.LinesAvail*-1)+1);
  469.                            broObject.FreeAll;
  470.                            ix := 1;
  471.                            while (ix <= broObject.LinesAvail) and
  472.                                  not File_EOF do
  473.                            begin
  474.                               broObject.Insert(FillInLine);
  475.                               if (ix < broObject.LinesAvail) then
  476.                                  GetRec(Next_Record);
  477.                               inc(ix);
  478.                            end;
  479.  
  480.                            {
  481.                            p := broObject.At(0);
  482.                            ln := p^.LineRcrd;
  483.                            Go(ln);
  484.                            ix := 1;
  485.                            GetRec(Prev_Record);
  486.                            while (ix < broObject.LinesAvail) and
  487.                                  not File_TOF do
  488.                            begin
  489.                               if broObject.Count >= broObject.LinesAvail then
  490.                                  broObject.Free
  491.                                            (broObject.At(broObject.Count-1));
  492.                               broObject.AtInsert(0,FillInLine);
  493.                               GetRec(Prev_Record);
  494.                               inc(ix);
  495.                            end;
  496.                            }
  497.                         end;
  498.  
  499.          else           begin
  500.                            if (action > 0) and (action <= NumRecs) then
  501.                            begin
  502.                               p := broObject.At(broObject.Count-1);
  503.                               ln := p^.LineRcrd;
  504.                               broObject.FreeAll;
  505.                               Go(action);
  506.                               ix := 0;
  507.                               while (ix < broObject. LinesAvail) and
  508.                                     not File_EOF do
  509.                               begin
  510.                                  broObject.Insert(FillInLine);
  511.                                  GetRec(Next_Record);
  512.                                  inc(ix);
  513.                               end;
  514.                            end;
  515.                         end;
  516.       end;
  517.    end;
  518. end;
  519.  
  520. Function GetBrowseHeader(bline: word): string;
  521. var
  522.    ix : integer;
  523.    p  : PByteArray;
  524.    t  : string;
  525. begin
  526.    p := pointer(broObject.LineHead);
  527.    ix := broObject.LinesWidth;
  528.    if (bline > (broObject.LineBufSize-ix) - 3) then
  529.    begin
  530.       GetBrowseHeader := '';
  531.       exit;
  532.    end;
  533.    move(p^[bline+3], t[1], ix);
  534.    t[0] := chr(ix);
  535.    GetBrowseHeader := t;
  536. end;
  537.  
  538. Function GetBrowseLine(linnum, bline: word): string;
  539. var
  540.    ix : integer;
  541.    p  : PByteArray;
  542.    t  : string;
  543. begin
  544.    if (linnum < 1) or (linnum > broObject.Count) then
  545.    begin
  546.       GetBrowseLine := '';
  547.       exit;
  548.    end;
  549.    p := broObject.At(linnum-1);
  550.    ix := broObject.LinesWidth;
  551.    if (bline > (broObject.LineBufSize-ix) - 3) then
  552.    begin
  553.       GetBrowseLine := '';
  554.       exit;
  555.    end;
  556.    move(p^[bline+3], t[1], ix);
  557.    t[0] := chr(ix);
  558.    GetBrowseLine := t;
  559. end;
  560.  
  561. Procedure RenewBrowseLine(linnum: word);
  562. var
  563.    ln : longint;
  564.    ix : integer;
  565.    p  : PByteArray;
  566.    t  : string;
  567. begin
  568.    ln := GetBrowseRecord(linnum);
  569.    if ln = 0 then exit;
  570.    go(ln);
  571.    p := broObject.At(linnum-1);
  572.    broObject.FreeItem(p);
  573.    broObject.AtPut(linnum-1,FillInLine);
  574. end;
  575.  
  576. Function GetBrowseRecord(linnum: integer): longint;
  577. var
  578.    lx : longint;
  579.    p  : PByteArray;
  580. begin
  581.    if (linnum < 1) or (linnum > broObject.Count) then
  582.    begin
  583.       GetBrowseRecord := 0;
  584.       exit;
  585.    end;
  586.    p := broObject.At(linnum-1);
  587.    move(p^,lx,4);
  588.    GetBrowseRecord := lx;
  589. end;
  590.  
  591. Function GetBrowseBar(bline: word): string;
  592. var
  593.    ix : integer;
  594.    t  : string;
  595. begin
  596.    t := GetBrowseHeader(bline);
  597.    for ix := 1 to length(t) do
  598.      if t[ix] = broSeparator then
  599.         t[ix] := broIntersect
  600.      else
  601.         t[ix] := broHorizontal;
  602.    GetBrowseBar := t;
  603. end;
  604.  
  605. end.
  606.  
  607.